package net.vinote.sosa.core.json;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import net.vinote.sosa.core.util.DateUtils;

/**
 * JSON工具类
 * 
 * @author Seer
 * @version JsonUtil.java, v 0.1 2015年11月5日 下午3:22:13 Seer Exp.
 */
public class JsonUtil {
	private static final Logger LOGGER = LogManager.getLogger(JsonUtil.class);

	/**
	 * 将List转化成json对象
	 * 
	 * @param key
	 * @param objArray
	 * @return
	 */
	public static <T> JSONObject getJsonObject(String key, List<T> objArray) {
		return getJsonObject(key, objArray.toArray());
	}

	/**
	 * 将List转化成JSONArray对象
	 * 
	 * @param objArray
	 * @return
	 */
	public static <T> JSONArray getJsonArray(List<T> objArray) {
		JSONArray jsonArray = new JSONArray();
		if (CollectionUtils.isEmpty(objArray)) {
			LOGGER.warn(" value is " + objArray);
			return jsonArray;
		}
		for (T t : objArray) {
			jsonArray.add(JsonUtil.getJsonObject(t));
		}
		return jsonArray;
	}

	/**
	 * 将数组转化成JSONArray对象
	 * 
	 * @param objArray
	 * @return
	 */
	public static <T> JSONArray getJsonArray(T[] objArray) {
		JSONArray jsonArray = new JSONArray();
		if (objArray == null) {
			LOGGER.warn(" value is " + objArray);
			return jsonArray;
		}
		for (T t : objArray) {
			jsonArray.add(JsonUtil.getJsonObject(t));
		}
		return jsonArray;
	}

	/**
	 * 将Map转化成JSONObject对象
	 *
	 * @param map
	 * @return
	 */
	public static <T> JSONObject getJsonMap(Map<String, T> map) {
		JSONObject jsonObject = new JSONObject();
		if (map == null) {
			LOGGER.warn(" value is " + map);
			return jsonObject;
		}
		for (Entry<String, T> entry : map.entrySet()) {
			JSONObject j = JsonUtil.getJsonObject(entry.getValue());
			jsonObject.put(entry.getKey(), j == null ? entry.getValue() : j);
		}
		return jsonObject;
	}

	/**
	 * 将数组转化成json对象
	 *
	 * @param key
	 * @param objArray
	 * @return
	 */
	public static <T> JSONObject getJsonObject(String key, T[] objArray) {
		JSONObject jsonObj = new JSONObject();
		if (key == null || objArray == null) {
			LOGGER.warn("invalid data convert to json, key is " + key + " , and value is " + objArray);
			return jsonObj;
		}
		JSONArray jsonArray = new JSONArray();
		for (T t : objArray) {
			jsonArray.add(JsonUtil.getJsonObject(t));
		}
		jsonObj.put(key, jsonArray);
		return jsonObj;
	}

	/**
	 * 将object对象转换成json对象
	 *
	 * <pre>
	 * 如果obj为某个类的子类，请确保子类与父类中不要存在同名的成员变量
	 * 
	 * </pre>
	 * 
	 * @param obj
	 * @return
	 */
	public static JSONObject getJsonObject(Object obj) {
		if (obj == null) {
			return null;
		}
		if (obj instanceof JSONObject) {
			return (JSONObject) obj;
		}
		if (obj instanceof ToJsonObject) {
			return ((ToJsonObject) obj).toJsonObject();
		}

		JSONObject json = new JSONObject();
		Class<?> curClass = obj.getClass();
		// 基本数据类型以及jdk提供的类不进行json转换

		if (curClass.isPrimitive() || curClass.getName().startsWith("java.lang")) {
			return null;
		}
		do {
			Field[] fields = curClass.getDeclaredFields();
			for (Field f : fields) {
				JSONAnnotation jsonAnnotation = f.getAnnotation(JSONAnnotation.class);
				// 过滤被final、static、JSONAnnotation修饰的成员变量
				if ((f.getModifiers() & Modifier.FINAL) > 0 || (f.getModifiers() & Modifier.STATIC) > 0
					|| (jsonAnnotation != null && jsonAnnotation.ignore())) {
					continue;
				}

				f.setAccessible(true);// 取消Field的访问检查

				String type = f.getType().getName();

				try {
					Object fileVal = f.get(obj);
					if (fileVal == null) {
						continue;
					}
					String keyName = f.getName();
					if (jsonAnnotation != null && StringUtils.isNotBlank(jsonAnnotation.alias())) {
						keyName = jsonAnnotation.alias();
					}
					// 根据value值获取真实类型
					type = fileVal.getClass().getName();

					// 基本数据类型、java.lang包、枚举

					if (f.getType().isPrimitive() || type.startsWith("java.lang")) {
						json.put(keyName, fileVal);
					} else if (Date.class.isInstance(fileVal)) {
						String dateStr = DateUtils.getDate((Date) fileVal, DateUtils.DEFAULT_FORMAT);
						json.put(keyName, dateStr);
					}
					// 数组循环填充

					else if (f.getType().isArray()) {
						Object[] objArray = (Object[]) fileVal;
						if (objArray == null || objArray.length == 0) {
							continue;
						}
						JSONArray arry = new JSONArray();
						for (Object o : objArray) {
							arry.add(getJsonObject(o));
						}
						json.put(keyName, arry);
					}
					// 集合循环填充

					else if (Collection.class.isInstance(fileVal)) {
						Collection<?> c = (Collection<?>) fileVal;
						if (CollectionUtils.isEmpty(c)) {
							continue;
						}
						JSONArray arry = new JSONArray();
						for (Object o : c) {
							arry.add(getJsonObject(o));
						}
						json.put(keyName, arry);
					} else if (JSONObject.class.isInstance(fileVal)) {
						json.put(keyName, fileVal);
					}
					// 循环Map

					else if (Map.class.isInstance(fileVal)) {
						Map<?, ?> map = (Map<?, ?>) fileVal;
						if (map == null || map.isEmpty()) {
							continue;
						}
						JSONArray array = new JSONArray();
						for (Object key : map.keySet()) {
							JSONObject jo = new JSONObject();
							jo.put(key.toString(), getJsonObject(map.get(key)));
							array.add(jo);
						}
						json.put(keyName, array);
					}
					// 其他类递归填充

					else {
						json.put(keyName, getJsonObject(fileVal));
					}
				} catch (Exception e) {
					LOGGER.warn("", e);
				}
			}
		} while ((curClass = curClass.getSuperclass()) != Object.class);
		return json;
	}
}